iT邦幫忙

2026 iThome 鐵人賽

DAY 23
0
Kubernetes

從零開始的雲端實戰:30 天 Kubernetes 核心觀念與部署指南系列 第 29

【Day 29】K8s 維運地獄:常見故障排除指南(CrashLoopBackOff、OOMKilled、Pending)

  • 分享至 

  • xImage
  •  

今日目標

  • 掌握 Kubernetes 疑難排解(Troubleshooting)的黃金 SOP 三板斧。
  • 深入解析最常見的三大崩潰狀態:PendingCrashLoopBackOffOOMKilled 的根本成因。
  • 掌握 ImagePullBackOffCreateContainerConfigError 等常見鏡像與設定錯誤。
  • 提供一目了然的排錯決策樹與實戰指令清單。

排錯黃金三板斧:除錯標準 SOP

當你執行 kubectl get pods 看到狀態不是綠色的 Running 時,請依照以下順序依序排查:

步驟 指令 排查重點
第一步:看狀態 kubectl get pods -o wide 確認 Pod 目前處於什麼狀態?運行在哪個 Node?重啟了幾次?
第二步:看事件 kubectl describe pod <pod-name> 滑到最下方的 Events 區塊,查看 Scheduler 與 Kubelet 的報錯事件。
第三步:看日誌 kubectl logs <pod-name> --previous 查看應用程式內部的崩潰堆疊(Stack Trace)。若容器已重啟,加上 --previous 看上一代的遺言。

災難一:Pod 卡在 Pending(排程失敗)

1. 現象說明

Pod 已經被建立,但 STATUS 一直停留在 PendingNODE 欄位顯示 <none>

2. 根本原因分析

kube-scheduler 找不到任何一個滿足條件的 Worker Node 來放置這個 Pod。

常見原因 排查與解決方式
節點運算資源不足(Insufficient CPU/Memory) 執行 kubectl describe pod 會看到 0/3 nodes are available: 3 Insufficient cpu.。代表所有節點剩餘算力低於 Pod 宣告的 requests。需擴容節點或調降 Pod 的 requests
節點帶有污點(Taints) 節點被上了 Taint(如 Master 節點預設不排程),而 Pod 沒有對應的 Toleration。
PVC 尚未綁定(PersistentVolumeClaim is not Bound) Pod 掛載的 PVC 處於 Pending 狀態(可能沒有符合條件的 PV 或 StorageClass 設定錯誤)。
節點標籤不匹配(nodeSelector / Affinity) Pod 指定了特定標籤(例如 disk=ssd),但集群中沒有任何節點帶有該標籤。

災難二:CrashLoopBackOff(容器反覆崩潰重啟)

1. 現象說明

Pod 狀態在 RunningErrorCrashLoopBackOff 之間不斷循環,RESTARTS 次數持續飆升。

2. 根本原因分析

容器裡面的應用程式在啟動後立刻非正常退出(Exit Code 非 0)。K8s 嘗試重啟它,但啟動又失敗,因此重試間隔會指數級拉長(Back-off Delay)。

常見原因 排查與解決方式
應用程式程式碼報錯 執行 kubectl logs <pod-name> --previous,通常能直接看到 Java NullPointerException、Node.js 模組缺失或語法錯誤。
缺少必要的環境變數或資料庫連線失敗 程式啟動時連不上 DB 或 Redis 直接拋出例外終止。檢查 ConfigMap / Secret 連線資訊。
主進程結束(Process Exited) 容器缺少常駐進程(如腳本執行完畢就退出,或啟動命令寫錯)。
健康檢查 Liveness Probe 誤殺 initialDelaySeconds 設定太短,應用程式還在暖機就被探針判定死亡並強行重啟。

災難三:OOMKilled (Exit Code 137)

1. 現象說明

Pod 的狀態顯示 OOMKilled,或者在 kubectl describe podLast State 中看到 Reason: OOMKilledExit Code: 137

2. 根本原因分析

OOM 代表 Out Of Memory(記憶體耗盡)

  • Exit Code 137 = 128 + 9 (SIGKILL),代表容器的記憶體使用量超過了在 YAML 裡設定的 resources.limits.memory
  • 節點的 Linux 核心 OOM-Killer 機制直接發送 SIGKILL 信號強制終止該容器,以保護節點上的其他應用不受影響。

3. 解決方案

  • 短期解法:在 YAML 檔中調高 resources.limits.memory
  • 長期解法:檢查應用程式是否存在 Memory Leak(記憶體洩漏),或調整 JVM 的 -Xmx 參數,確保 JVM 最大堆積記憶體小於容器的 limit 上限。

其他常見的高頻錯誤一覽

錯誤狀態 核心成因 解決方案
ImagePullBackOff / ErrImagePull 映像檔名稱打錯、Tag 不存在,或是私有倉庫(Private Registry)缺少 imagePullSecrets 認證。 檢查 Image 拼字,或建立 docker-registry 類型的 Secret 進行授權。
CreateContainerConfigError Pod 引用的 ConfigMap 或 Secret 根本不存在,或是 Key 名稱拼錯。 執行 kubectl describe pod 確認缺少的 ConfigMap/Secret 名稱並建立它。
ContainerCannotRun 容器啟動指令(command / args)路徑錯誤或權限不足(例如執行了一個不存在的 entrypoint 腳本)。 檢查 Dockerfile 與 Pod YAML 的 command 設定。

終極排錯決策樹

遇到 Pod 故障時的快速決策清單:

  1. 先看 STATUS 是什麼?
    • 若是 Pending ➔ 直接執行 kubectl describe pod 查看 Events(一定是調度、資源或磁碟問題)。
    • 若是 ImagePullBackOff ➔ 檢查映像檔路徑與 Secret 權限。
    • 若是 CrashLoopBackOff ➔ 進入下一步看日誌。
  2. 查詢容器日誌(Logs)
    • 執行 kubectl logs <pod-name>
    • 若無日誌,加上 --previous 查看上一代容器死亡時的 Log。
  3. 檢查退出碼(Exit Code)
    • 執行 kubectl describe pod <pod-name>
    • 若看到 Exit Code 137 ➔ 100% 是記憶體超出限制(OOMKilled)。
    • 若看到 Exit Code 0 ➔ 容器正常跑完退出,可能是誤把一次性 Job 寫成了 Deployment。

本日小結

今天我們系統化地梳理了 Kubernetes 最核心的故障排除方法論:

  • 建立了標準的排錯 SOP(getdescribelogs)。
  • 徹底搞懂了 Pending(排程卡關)CrashLoopBackOff(應用崩潰)OOMKilled(記憶體超標) 的底層機理與解法。

明天就是鐵人賽的最終篇 Day 30!我們將進行全系列 30 天的知識體系大盤點:「【完賽總結】從零到 Kubernetes 實戰架構師:30 天全系列回顧與進階學習藍圖」


上一篇
【Day 28】雲端託管 K8s 實戰:AWS EKS vs. GCP GKE 架構比較與架構選型
下一篇
【Day 30】從零到 Kubernetes 實戰架構師:30 天全系列回顧與進階學習藍圖
系列文
從零開始的雲端實戰:30 天 Kubernetes 核心觀念與部署指南30
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言